package cn.edu.hust.cm.lib.sql;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import cn.edu.hust.cm.lib.JavaLog;

/**
 * 自定义的数据库连接池. 可能有性能问题
 * 
 * @author Administrator
 * 
 */
class DbConnPool {

	@Override
	public String toString() {
		return "DbConnPool [busyQueue=" + busyQueue.size() + ", idleQueue="
				+ idleQueue.size() + ", available()=" + available() + "]";
	}

	private Queue<Connection> idleQueue = new ConcurrentLinkedQueue<Connection>();
	private Queue<Connection> busyQueue = new ConcurrentLinkedQueue<Connection>();

	// 防止单例模式起作用
	private static final boolean DEBUG = false;

	private DbConnPool() {
		int init = DbUtil.getPoolSizeInitial();
		// 初始化时往queue中添加几个数据库连接, 数量由database.pool.size.initial设置
		for (int i = 0; i < init; i++) {
			idleQueue.add(register(DbUtil.getConnectionFromDriver()));
		}
	}

	private static class DbConnPoolHolder {
		private static final DbConnPool INSTANCE;

		static {
			INSTANCE = new DbConnPool();
		}
	}

	static DbConnPool getInstance() {
		if (DEBUG) {
			return new DbConnPool();
		}
		return DbConnPoolHolder.INSTANCE;
	}

	/**
	 * 从连接池中获取一个连接. 如果必要, 会新建连接
	 * 
	 * @return
	 */
	synchronized Connection get() {
		Connection conn = idleQueue.poll();
		if (null != conn) {
			busyQueue.offer(conn);
		}
		if (null == conn && busyQueue.size() < DbUtil.getPoolSizeMax()) {
			conn = register(DbUtil.getConnectionFromDriver());
			busyQueue.offer(conn);
		}

		return conn;
	}

	/**
	 * 将一个连接归还给连接池
	 * 
	 * @param conn
	 */
	synchronized void put(Connection conn) {
		idleQueue.offer(conn);
		busyQueue.remove(conn);
	}

	/**
	 * 将连接附着到连接池上
	 * 
	 * @param conn
	 *            数据库连接
	 * @return
	 */
	private ConnectionWrapper register(ConnectionWrapper conn) {
		conn.attach(this);
		return conn;
	}

	/**
	 * 返回空闲连接数
	 * 
	 * @return 空闲连接数
	 */
	public int idle() {
		return idleQueue.size();
	}

	/**
	 * 返回可用连接数
	 * 
	 * @return 可用连接数
	 */
	public int available() {
		return DbUtil.getPoolSizeMax() - busyQueue.size();
	}

	/**
	 * 返回正在使用的连接数
	 * 
	 * @return
	 */
	public int busy() {
		return busyQueue.size();
	}

	public void shutdown() {
		try {
			for (Connection c : busyQueue) {
				c.close();
			}
		} catch (SQLException e) {
			JavaLog.e(e.getMessage());
		}

		try {
			for (Connection c : idleQueue) {
				c.close();
			}
		} catch (SQLException e) {
			JavaLog.e(e.getMessage());
		}

		busyQueue.clear();
		idleQueue.clear();
	}

}
